﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using PubSub.S3.Abstract;
using PubSub.S3.Abstract.DistributeEventBus;
using PubSub.S3.Abstract.LocalEventBus;
using PubSub.S3.EventName;
using PubSub.S3.Redis;

namespace PubSub.S3.Test
{
    public class Level3
    {
        [EventName("event_pubsub")]
        public class RedisMessage : EventDataAbstract
        {
            public string SiteKey { get; set; }

            public string TenantCode { get; set; }
        }

        private static IEventBus _pubEventBus = new RedisEventBus();
        private static IEventBus _subEventBus = new RedisEventBus();

        public static async Task TestPubSubByObject()
        {
            // await Task.Run(() =>
            // {
            // SubscribeAction();
            // SubscribeTransientEventHandler();
            // SubscribeInstanceEventHandler();
            //var factorySub = _subEventBus.Subscribe<RedisMessage>(new TransientEventHandlerFactory<TestDistributeEventHandler>());
            // });

            Task.Run(async () => { await Task.Delay(5000); })
                .ContinueWith(t =>
            {
                //_subEventBus.UnsubscribeAll(typeof(RedisMessage));

                //_subEventBus.Unsubscribe(action);
                // _subEventBus.Unsubscribe(typeof(RedisMessage),eventHandler);
                //_subEventBus.Unsubscribe(eventHandler);
                //factorySub.Dispose();

                // actoinSub.Dispose();
                //transientSub.Dispose();
                //instanceSub.Dispose();
            });

            await Task.Run(async () =>
            {
                while (true)
                {
                    await Task.Delay(1000);
                    await PublishByObject();
                    await Console.Out.WriteLineAsync(
                        $"{Environment.NewLine}--- publish ---  {DateTime.Now:HH:mm:ss ffff}");
                }
            });
        }

        public static async Task TestPublishByType()
        {
            await Task.Run(() =>
            {
                SubscribeAction();
                SubscribeTransientEventHandler();
                SubscribeInstanceEventHandler();
            });
            await PublishByType();
        }

        public static async Task TestAction()
        {
            await Task.Run(SubscribeAction);
            await PublishByObject();
        }

        public static async Task TestTransient()
        {
            await Task.Run(SubscribeTransientEventHandler);
            await PublishByObject();
        }

        public static async Task TestSingleInstance()
        {
            await Task.Run(SubscribeInstanceEventHandler);
            await PublishByObject();
        }

        public static void SubscribeHandlerFactory()
        {
        }

        // class HandlerFactory : IEventHandlerFactory
        // {
        //     public IEventHandlerDisposeWrapper GetHandler()
        //     {
        //         return new EventHandlerDisposeWrapper();
        //     }
        //
        //     public bool IsInFactories(List<IEventHandlerFactory> handlerFactories)
        //     {
        //         throw new NotImplementedException();
        //     }
        // }


        //Transient
        private static IDisposable transientSub;

        static void SubscribeTransientEventHandler()
        {
            transientSub = _subEventBus.Subscribe<RedisMessage, TestDistributeEventHandler>();
        }

        //action
        //ILocalEventHandler
        private static IDisposable actoinSub;

        private static Func<RedisMessage, Task> action = value =>
        {
            Console.WriteLine($"SubscribeAction  {value.CreateTime:HH:mm:ss ffff}");
            return Task.CompletedTask;
        };

        static void SubscribeAction()
        {
            actoinSub = _subEventBus.Subscribe<RedisMessage>(action);
        }

        //SingleInstance
        private static IDisposable instanceSub;
        private static ILocalEventHandler<RedisMessage> eventHandler = new TestLocalEventHandler();
        static void SubscribeInstanceEventHandler()
        {
            instanceSub = _subEventBus.Subscribe(typeof(RedisMessage), eventHandler);
        }

        private class TestDistributeEventHandler : IDistributedEventHandler<RedisMessage>
        {
            public Task HandleEventAsync(RedisMessage eventData)
            {
                Console.WriteLine($"TestDistributeEventHandler {eventData.CreateTime:HH:mm:ss ffff}");

                return Task.CompletedTask;
            }
        }

        private class TestLocalEventHandler : ILocalEventHandler<RedisMessage>
        {
            public Task HandleEventAsync(RedisMessage eventData)
            {
                Console.WriteLine($"TestLocalEventHandler {eventData.CreateTime:HH:mm:ss ffff}");

                return Task.CompletedTask;
            }
        }


        static async Task PublishByObject()
        {
            // IEventBus publish = new RedisEventBus();
            var message = new RedisMessage()
            {
                //FuncType = FuncTypeEnum.Default,
                SiteKey = "erp60",
                TenantCode = "mysoft",
                CreateTime = DateTime.Now
            };
            await _pubEventBus.PublishAsync(message);
        }

        static async Task PublishByType()
        {
            var message = new RedisMessage()
            {
                //FuncType = FuncTypeEnum.Default,
                SiteKey = "erp60",
                TenantCode = "mysoft",
                CreateTime = DateTime.Now
            };
            await _pubEventBus.PublishAsync(typeof(RedisMessage), message);
        }
    }
}